package com.csjy.migration.hnnd.workflow;

import com.csjy.migration.hnnd.*;
import com.csjy.migration.hnnd.annotation.Task;
import com.csjy.migration.hnnd.business.*;
import com.csjy.migration.hnnd.dict.Bank;
import com.csjy.migration.hnnd.dict.RepayType;

import javax.script.ScriptException;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 核保放款流程
 */
public class ItemSencorLoanHny extends WorkflowMigration {
  private NdBpmProjectArchive ndBpmProjectArchive = null;
  private NdBpmFeeCollectionRecord ndBpmFeeCollectionRecord = null;
  private NdBpmResponsibilityLoan ndBpmResponsibilityLoan = null;
  private NdBpmGuaranteeDetails ndBpmGuaranteeDetails = null;
  private NdbBpmLoanInformationForm ndbBpmLoanInformationForm = null;

  private String approvalType = "";

  public ItemSencorLoanHny(DbUtil sourceDbUtil, DbUtil targetDbUtil, SourceBusinessData sourceData, ProgramArgument programArgument, String projectId, String procInstId, Map procInstRow) throws Exception {
    super(sourceDbUtil, targetDbUtil, sourceData, programArgument, projectId, procInstId, procInstRow);
    this.customInitData();
  }


  @Override
  public void customInitData() throws SQLException {
    this.curBizType = "hbfk";
    ndBpmProjectArchive  = new NdBpmProjectArchive(this.sourceDbUtil,this.targetDbUtil,sourceData, programArgument,this.projectId,this.procInstId);
    ndBpmFeeCollectionRecord = new NdBpmFeeCollectionRecord(sourceDbUtil,targetDbUtil,sourceData,programArgument,projectId,procInstId);
    ndBpmResponsibilityLoan = new NdBpmResponsibilityLoan(sourceDbUtil, targetDbUtil, sourceData, programArgument, projectId, procInstId);
    ndBpmGuaranteeDetails = new NdBpmGuaranteeDetails(sourceDbUtil, targetDbUtil, sourceData, programArgument, projectId, procInstId);
    ndbBpmLoanInformationForm = new NdbBpmLoanInformationForm(sourceDbUtil, targetDbUtil, sourceData, programArgument, projectId, procInstId);
  }

  @Override
  public void customInsertOrUpdateData() throws Exception {
    ndBpmProjectArchive.start();
    ndBpmFeeCollectionRecord.start();
    ndBpmResponsibilityLoan.start();
    ndBpmGuaranteeDetails.start();
    ndbBpmLoanInformationForm.start();
  }


  @Task("核保放款@项目经理提交核保资料")
  public void xmjltjhbzl() throws Exception {
    this.curAffixType = "mqzl";
    this.curAffixTypeCommon = this.curAffixType;

    this.curModelMap.put("all", new String[] {"exclusiveGateway1594091915669tg","通过"});
    this.setCommonData(false,null);
    // 项目评审会结论 报告等 (自动抓取?)

    // ====申请金额情况核实====
    // 审批类型
    String sencorType = this.getJbpmVarInstValueByName("sencorType");
    if(sencorType != null) {
      if (sencorType.equals("核保放款")) {
        this.curCustomData.put("approvalType", "1");
      } else if (sencorType.equals("核保")) {
        this.curCustomData.put("approvalType", "2");
      } else if (sencorType.equals("放款")) {
        this.curCustomData.put("approvalType", "3");
      }
      this.approvalType = this.curCustomData.get("approvalType").toString();

    }
    //


    // 关联项目在保总额
    this.curCustomData.put("coverageMoney","0");
      // 已签保证合同金额
    this.curCustomData.put("guaranteedContractAmount",this.getJbpmVarInstValueByName("totalOutAskSum"));
    // 可签保证合同金额
    this.curCustomData.put("contractableContractAmount",this.getJbpmVarInstValueByName("allCanUseSum"));
    // 在保总额
    this.curCustomData.put("coverageMoney1",this.getJbpmVarInstValueByName("askDeferSum"));

    // 委托担保协议编号
    this.curCustomData.put("assuContractNo",this.getJbpmVarInstValueByName("assuContractNo"));
    // 委托担保协议开始时间
    this.curCustomData.put("agreeTimeStart",this.getJbpmVarInstValueByName("assuContractBtime"));
    // 委托担保协议到期时间
    this.curCustomData.put("agreeTimeEnd",this.getJbpmVarInstValueByName("assuContractEtime"));
    // 客户还款方式(新老系统字典内容完全不一样)
    this.curCustomData.put("repayType",sourceData.getRepayType());
    // 还款计划
    this.curCustomData.put("repaymentPlanHy","还款方式："+BusinessTool.getOldDictDataNameByDictCodeAndDataCode("35",this.getJbpmVarInstValueByName("returnWay"))
        +" 还款计划："+ BusinessTool.getOldDictDataNameByDictCodeAndDataCode("46",this.getJbpmVarInstValueByName("planFlag")));
    this.curCustomData.put("everyAverageMoney","还款方式："+ BusinessTool.getOldDictDataNameByDictCodeAndDataCode("35",this.getJbpmVarInstValueByName("returnWay"))
        +" 还款计划："+ BusinessTool.getOldDictDataNameByDictCodeAndDataCode("46",this.getJbpmVarInstValueByName("planFlag")));

    // *****************************************老系统中独有的信息*************************//
    // 项目授信总额(新系统是动态查询的） transacAssureSum
    // 已占用放款额 totalOutAskSum
    // 可用申请余额 = 授信总额-已占用放款额 availableApplySum
    // 项目原在保额 askDeferSum
    // 出保银行 promBank
    // 出保银行支行 bankBranchName
    // 原已出保金额 totalOutPromSum
    // 是否按年收取担保费 assFareWay
    // 保证合同编号 promContractNo
    // 最高额度保证合同 checkMaxPromCont
    // 凭放用款通知书 checkRequition
    // 本次出保金额 promSum
    // 担保项目品种 assureClass
    // 保证合同开始时间 promContBtime
    // 保证合同结束时间 promContEtime
    // 贷款合同编号 loanContractNo
    // 客户还款方式 returnWay
    // 还款计划 planFlag
    // 月利率 monthRate
    // 年利率 yearRate
    // 本次申请放款额 thisAskUseSum
    // 客户开户银行 clientBankId
    // 客户放款账号 clientBankAccount

    for(Map<String,Object> jbpmVar: jbpmVariableInstanceList){
      if(jbpmVar.get("TASKINSTANCE_") !=null){
        continue;
      }
      this.curCustomData.put("jwframe_"+jbpmVar.get("NAME_"), jbpmVar.get("STRINGVALUE_"));
    }

    // 出保银行 promBank
    this.curCustomData.put("jwframe_promBank", DictTool.getTargetDictCode(Bank.class,this.getJbpmVarInstValueByName("promBank")));
    // 客户开户银行 clientBankId
    this.curCustomData.put("jwframe_clientBankId", DictTool.getTargetDictCode(Bank.class,this.getJbpmVarInstValueByName("clientBankId")));
    // 担保项目品种 assureClass
    this.curCustomData.put("jwframe_assureClassName", BusinessTool.getOldDictDataNameByDictCodeAndDataCode("12",this.getJbpmVarInstValueByName("assureClass")));
    // 还款计划 planFlag
    this.curCustomData.put("jwframe_planFlag", this.getJbpmVarInstValueByName("planFlag"));
    this.curCustomData.put("jwframe_planFlagName", BusinessTool.getOldDictDataNameByDictCodeAndDataCode("46",this.getJbpmVarInstValueByName("planFlag")));

    // TODO: 项目基本信息(老系统是没有的,新系统独有,待收担保费:premiumToBePaid) 从老系统中拿
    String[] ndProjectInfoFields = new String[] {
        "isMicro","guaranteeRate","productName","industry","industryCode","customerSource","institution1","institution2"
        ,"institution3","summary","premiumToBePaid","creditTimeStart","creditTimeEnd"};
    getDataField(ndProjectInfoFields);

    // 保证合同金额
    String promContractNo = this.getJbpmVarInstValueByName("promContractNo");
    Object guaranteedContractAmount = null;
    if (!(promContractNo == null || promContractNo.equals(""))) {
      guaranteedContractAmount = BusinessTool.getGuaranteeContractAmount(promContractNo,  this.sourceData);// 保证合同金额
      if(guaranteedContractAmount == null || guaranteedContractAmount.toString().equals("0")) {
        Object promSum = this.getJbpmVarInstValueByName("promSum");
        if(!(promSum == null || promSum.toString().equals(""))) {
          guaranteedContractAmount = new BigDecimal(this.getJbpmVarInstValueByName("promSum"));
        }
      }
    }

    // ========放款信息表=======
    Map<String,Object> taskParamMap = this.initTaskParamMap();
    taskParamMap.put("guaranteedContractAmount", guaranteedContractAmount);
    // 正在运行中的流程 自己构造放款信息记录
    Map<String,Object> customNdLoanInformation = this.buildNdLoanInformation();
    customNdLoanInformation.put("guaranteedContractAmount", guaranteedContractAmount);
    taskParamMap.put("customNdLoanInformation", customNdLoanInformation);

    this.ndbBpmLoanInformationForm.getTaskParamMap().put(curJbpmTaskInstanceId, taskParamMap);
    // 可选
    this.ndBpmResponsibilityLoan.getTaskParamMap().put(curJbpmTaskInstanceId, taskParamMap);

    // =======应缴银行保证金=======
    // 缴存银行
    this.curCustomData.put("bank2",DictTool.getTargetDictCode(Bank.class,this.getJbpmVarInstValueByName("yhmc")));
    this.curCustomData.put("bank2Name",BusinessTool.getOldDictDataNameByDictCodeAndDataCode("33",this.getJbpmVarInstValueByName("yhmc")));
    // 缴存账号
    this.curCustomData.put("accountNumber",this.getJbpmVarInstValueByName("yhzh"));
    // 应缴存金额
    this.curCustomData.put("amountMoney",this.getJbpmVarInstValueByName("yjje"));

    // ========原客户收费记录（收费、退费）-老系统独有 (核保放款和只放款独有) - 同一项目其他流程产生的在 bt_item_fare_detail 表=======

    // ========本次应收费清单列表(可增删改,老系统只有放款的才有)- bt_item_charge_audit表=============
    this.ndBpmFeeCollectionRecord.getTaskParamMap().put(this.curJbpmTaskInstanceId,  this.initTaskParamMap());

    // ========未放款核保记录（签订了保证合同的未放款的,老系统独有，只读：不用管）============

    // ==========项目台账记录(老系统独有，只读 ：不用管)======================

    // =============资料移交清单=======================
    Map<String,Object> taskParam = this.initTaskParamMap();
    taskParam.put("isPigeonhole", "1");
    taskParam.put("archiveCategory", "");
    ndBpmProjectArchive.getTaskParamMap().put(this.curJbpmTaskInstanceId, taskParam);

    // ============保证合同和借款合同===================
    /**
     * 1.  项目经理提交核保资料环节
     * 判断 核保放款 类型
     * a. 若是 只核保  则不插入 合同表
     * b. 否则 要插入 合同表
     */
    //  判断核保放款类型
    if(!"2".equals(approvalType) && !approvalType.equals("")){

      if(!(this.getJbpmVarInstValueByName("promSum") == null || this.getJbpmVarInstValueByName("promSum").equals(""))) {

        /**
         * 2. 项目经理提交核保资料 环节
         *  插入两次合同表
         */
        // 保证合同

        if (!(promContractNo == null || promContractNo.equals(""))) {
          Map<String, Object> detail = new HashMap<>();
          detail.put("promBank", this.getJbpmVarInstValueByName("promBank"));//出保银行名称
          detail.put("promContractNo", promContractNo);//保证合同编号
          detail.put("promContBtime", this.getJbpmVarInstValueByName("promContBtime"));//保证合同开始时间
          detail.put("promContEtime", this.getJbpmVarInstValueByName("promContEtime"));//保证合同到期时间
          detail.put("bankBranchName", this.getJbpmVarInstValueByName("bankBranchName"));//银行支行名称
          detail.put("contractType", "1");//合同类型
          detail.put("guaranteedContractAmount",guaranteedContractAmount);// 保证合同金额

          ndBpmGuaranteeDetails.customMigrate(detail, curJbpmTaskInstanceId, this.initTaskParamMap());
        }

        // 贷款合同
        String loanContractNo = this.getJbpmVarInstValueByName("loanContractNo");

        if (!(loanContractNo == null || loanContractNo.equals(""))) {
          Map<String, Object> detailLoan = new HashMap<>();
          detailLoan.put("loanContractNo", this.getJbpmVarInstValueByName("loanContractNo"));//借款合同编号
          detailLoan.put("yearRate", this.getJbpmVarInstValueByName("yearRate"));//年利率
          detailLoan.put("returnWay", this.getJbpmVarInstValueByName("returnWay"));//客户还款方式,todo 数据字典不同，暂时同样的处理
          detailLoan.put("contractType", "2");//合同类型
          detailLoan.put("repaymentMethod", this.getJbpmVarInstValueByName("repaymentMethod"));//todo 数据字典不同，暂时同样的处理
          detailLoan.put("promBank", this.getJbpmVarInstValueByName("promBank"));//出保银行名称
          detailLoan.put("promContractNo", this.getJbpmVarInstValueByName("promContractNo"));//保证合同编号
          detailLoan.put("promContBtime", this.getJbpmVarInstValueByName("promContBtime"));//保证合同开始时间
          detailLoan.put("promContEtime", this.getJbpmVarInstValueByName("promContEtime"));//保证合同到期时间
          detailLoan.put("bankBranchName", this.getJbpmVarInstValueByName("bankBranchName"));//银行支行名称
          detailLoan.put("guaranteedContractAmount",guaranteedContractAmount);// 保证合同金额

          ndBpmGuaranteeDetails.customMigrate(detailLoan, curJbpmTaskInstanceId, this.initTaskParamMap());
        }
      }
    }

    ndbBpmLoanInformationForm.setLastFirstTaskId(this.curJbpmTaskInstanceId);
  }

  private Map buildNdLoanInformation() {
    Map<String,Object> row = new HashMap();
    row.put("sencorType", this.getJbpmVarInstValueByName("sencorType"));
    row.put("ACCOUNTNO", MD5Utils.stringToMD5(this.projectId + this.procInstId + this.curJbpmTaskInstanceId));
    row.put("PROMCONTRACTNO", this.getJbpmVarInstValueByName("promContractNo"));
    row.put("LOANCONTRACTNO", this.getJbpmVarInstValueByName("loanContractNo"));
    row.put("OCCURSUM", this.getJbpmVarInstValueByName("thisAskUseSum"));
    row.put("YEARRATE", this.getJbpmVarInstValueByName("yearRate"));
    row.put("BANKID", this.getJbpmVarInstValueByName("promBank")); // TODO: 放款银行 和 出保银行 一样吗?需要确认
    row.put("BANKBRANCH", this.getJbpmVarInstValueByName("bankBranchName"));
    row.put("CLIENTBANKACCOUNT", this.getJbpmVarInstValueByName("clientBankAccount")); // TODO: 客户开户银行 clientBankId
    row.put("WORKFLOWNO", this.procInstId);

    return row;
  }

  @Task("核保放款@风控部和财务审核处理")
  public void fkbhcwshcl() throws Exception {
    this.curModelMap.put("通过", new String[] {"task1558073185325tg","通过"});
    this.curModelMap.put("all", new String[] {"task1558073185325tg","通过"});

    this.setCommonData(false,null);
    this.setFengkongAndCaiwuData();
  }

  @Task("核保放款@风控副总审核处理")
  public void fkfzshcl() throws Exception {
    this.curModelMap.put("通过", new String[] {"exclusiveGateway1587093491467tg","通过"});
    this.curModelMap.put("all", new String[] {"task1558073185325tg","通过"});
    this.setCommonData(false,null);
  }

  // 老流程
  @Task("核保放款@风控部审核处理")
  public void fkbshcl() throws Exception {
    this.curModelMap.put("通过", new String[] {"task1558073185325tg","通过"});
    this.curModelMap.put("all", new String[] {"task1558073185325tg","通过"});
    this.setCommonData(false,null);
    this.setFengkongAndCaiwuData();
  }

  // 老流程
  @Task("核保放款@风控副总审核和财务处理")
  public void fkfzshhcwcl() throws Exception {
    this.curModelMap.put("通过", new String[] {"task1558073185325tg","通过"});
    this.curModelMap.put("all", new String[] {"task1558073185325tg","通过"});
    this.setCommonData(false,null);
    this.setFengkongAndCaiwuData();
  }

  @Task("核保放款@总经理审核批字")
  public void zjlshpz() throws Exception {
    this.curModelMap.put("同意", new String[] {"task1558073185325tg","通过"});
    this.curModelMap.put("通过", new String[] {"task1558073185325tg","通过"});
    this.curModelMap.put("不通过", new String[] {"task1558073185325tg","不通过"});
    this.setCommonData(false,null);
  }

  @Task("核保放款@总经理审核签字")
  public void zjlshqz() throws Exception {
    this.curModelMap.put("同意", new String[] {"task1558073185325tg","通过"});
    this.curModelMap.put("通过", new String[] {"task1558073185325tg","通过"});
    this.curModelMap.put("不通过", new String[] {"task1558073185325tg","不通过"});
    this.setCommonData(false,null);
  }

  @Task("核保放款@董事长审批签字")
  public void dszspqz() throws Exception {
    this.curModelMap.put("通过", new String[] {"task1558073185325tg","通过"});
    this.curModelMap.put("不通过", new String[] {"task1558073185325tg","不通过"});
    this.setCommonData(false,null);
  }

  @Task("核保放款@项目经理确认放款")
  public void xmjlqrfk() throws Exception {
    this.curModelMap.put("all", new String[] {"task1558073185325tg","通过"});
    this.curAffixType= "fkpz";
    this.setCommonData(true,null);
    this.curCustomData.put("taskName","核保放款@项目经理确认放款");
    this.setContractNoData();
    this.setFangkuanData(true);
  }

  @Task("核保放款@综合人员复核台账")
  public void zhryfhtz() throws Exception {
    this.jhzhryfhtz();
  }

  @Task("核保放款@#综合人员复核台账")
  public void jhzhryfhtz() throws Exception {
    this.curModelMap.put("all", new String[] {"task1558073185325tg","通过"});
    this.setCommonData(false,null);
    this.curCustomData.put("taskName","核保放款@综合人员复核台账");
    this.setFangkuanData(true);
  }

  @Task("核保放款@项目经理补填合同编号")
  public void migrationGsrzbsp() throws Exception {
    this.curModelMap.put("all", new String[] {"task1558073185325tg","通过"});
    this.setCommonData(false,null);
    this.curCustomData.put("taskName","核保放款@项目经理补填合同编号");
    this.setContractNoData();
  }

  // 设置放款数据
  public void setFangkuanData(boolean isCheck) {
    // 实际放款金额
    this.curCustomData.put("sureAskUseSum",this.getJbpmVarInstValueByName("sureAskUseSum"));
    // 还款年息利率
    this.curCustomData.put("monthRate",this.getJbpmVarInstValueByName("monthRate"));
    // 放款发生时间
    this.curCustomData.put("accountBtime",this.getJbpmVarInstValueByName("accountBtime"));
    // 放款到期时间
    this.curCustomData.put("accountEtime",this.getJbpmVarInstValueByName("accountEtime"));
    if(isCheck) {
      // 放款复核时间
      this.curCustomData.put("checkTime",this.getJbpmVarInstValueByName("checkTime"));
    }
    // 实际放款银行
    this.curCustomData.put("exPromBank",this.getJbpmVarInstValueByName("exPromBank"));
    this.curCustomData.put("exPromBankName",this.getJbpmVarInstValueByName("exPromBank") == null ? null : BusinessTool.getOldDictDataNameByDictCodeAndDataCode("33", this.getJbpmVarInstValueByName("exPromBank").toString()));
    // 银行支行名称
    this.curCustomData.put("exBankBranchName",this.getJbpmVarInstValueByName("exBankBranchName"));
  }

  // 设置合同编号数据
  public void setContractNoData() {
    // 贷款合同编号
    this.curCustomData.put("sloanContractNo",this.getJbpmVarInstValueByName("sloanContractNo"));
    // 保证合同编号
    this.curCustomData.put("spromContractNo",this.getJbpmVarInstValueByName("spromContractNo"));
    // 保证合同开始时间
    this.curCustomData.put("spromContBtime",this.getJbpmVarInstValueByName("spromContBtime"));
    // 保证合同到期时间
    this.curCustomData.put("spromContEtime",this.getJbpmVarInstValueByName("spromContEtime"));
  }

  // 设置风控和财务处理数据
  public void setFengkongAndCaiwuData() throws SQLException, ScriptException {
    // 客户应收费清单列表
    this.ndBpmFeeCollectionRecord.getTaskParamMap().put(this.curJbpmTaskInstanceId,  this.initTaskParamMap());
    // 担保协议编号（风控处理）
    this.curCustomData.put("reset_assuContractNo",this.getJbpmVarInstValueByName("reset_assuContractNo"));
    // 担保费收取方式
    this.curCustomData.put("assFareWay",this.getJbpmVarInstValueByName("assFareWay"));
    // 银行实转保证金信息
    // 转存银行
    this.curCustomData.put("bank","");
    // 实缴金额
    this.curCustomData.put("amountMoney","");
    // 到期时间
    this.curCustomData.put("eandDate","");

    Map btItemBankBailAccount = null;
    for(int i = 0;i<this.sourceData.getBtItemBankBailAccount().size();i++) {
      Map btItemBankBailAccountLoop = this.sourceData.getBtItemBankBailAccount().get(i);
      if(btItemBankBailAccountLoop.get("WORKFLOWNO").toString().equals(this.procInstId)){
        btItemBankBailAccount = btItemBankBailAccountLoop;
        break;
      }
    }

    if(btItemBankBailAccount != null) {
        this.curCustomData.put("bank", DictTool.getTargetDictCode(Bank.class, btItemBankBailAccount.get("BANKID")));
        // 实缴金额
        this.curCustomData.put("amountMoney",btItemBankBailAccount.get("OCCURSUM"));
        // 到期时间
       Object endTime = btItemBankBailAccount.get("ENDTIME");
       if(endTime == null || endTime.toString().equals("")) {
         this.curCustomData.put("eandDate","");
       }else{
         this.curCustomData.put("eandDate",((Timestamp) endTime).toLocalDateTime().toLocalDate().toString());
       }
    }
  }

}

